package com.dify.knowledge.service;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dify.knowledge.entity.Document;
import com.dify.knowledge.entity.DocumentVersion;
import com.dify.knowledge.exception.DocumentProcessingException;
import com.dify.knowledge.repository.DocumentMapper;
import com.dify.knowledge.repository.DocumentVersionMapper;
import com.dify.knowledge.util.DocumentTextExtractor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.*;

/**
 * 文档管理服务
 */
@Slf4j
@Service
public class DocumentService {

    private final DocumentMapper documentMapper;
    private final DocumentVersionMapper documentVersionMapper;
    private final DifyService difyService;

    @Value("${file.upload.path}")
    private String uploadPath;

    @Value("${file.upload.allowed-types}")
    private String allowedTypes;

    public DocumentService(DocumentMapper documentMapper,
                          DocumentVersionMapper documentVersionMapper,
                          DifyService difyService) {
        this.documentMapper = documentMapper;
        this.documentVersionMapper = documentVersionMapper;
        this.difyService = difyService;
    }

    /**
     * 上传并处理文档
     * @param file 上传的文件
     * @param userId 用户ID
     * @return 文档上传结果
     */
    @Transactional(rollbackFor = Exception.class)
    public DocumentUploadResult uploadDocument(MultipartFile file, Long userId) {
        log.info("开始处理文档上传，文件名：{}，用户ID：{}", file.getOriginalFilename(), userId);

        // 验证文件
        validateFile(file);

        String originalFilename = file.getOriginalFilename();
        String fileType = determineFileType(originalFilename);
        
        try {
            // 直接从内存中提取文本内容，不保存到本地
            log.info("开始提取文档文本，文件名：{}", originalFilename);
            String extractedText = extractTextFromMultipartFile(file, fileType);

            // 检查是否已存在同名文档
            Document existingDocument = documentMapper.selectByFileName(originalFilename);
            
            Document document;
            int nextVersionNumber;
            
            if (existingDocument != null) {
                // 如果文档已存在，作为新版本处理
                log.info("发现同名文档，作为新版本处理，文档ID：{}", existingDocument.getId());
                document = existingDocument;
                
                // 获取当前最大版本号
                Integer maxVersion = documentVersionMapper.selectMaxVersionByDocumentId(document.getId());
                nextVersionNumber = (maxVersion != null ? maxVersion : 0) + 1;
                
                // 更新文档信息
                document.setFileSize(file.getSize());
                document.setStatus("PROCESSING");
                documentMapper.updateById(document);
            } else {
                // 创建新文档记录
                log.info("创建新文档记录");
                document = new Document();
                document.setFileName(originalFilename);
                document.setFileType(fileType);
                document.setFileSize(file.getSize());
                document.setFilePath(null);
                document.setUploadUserId(userId);
                document.setStatus("PROCESSING");
                document.setCreatedAt(LocalDateTime.now());
                documentMapper.insert(document);
                
                nextVersionNumber = 1;
            }

            // 上传到Dify知识库
            log.info("开始上传到Dify知识库，文档ID：{}，版本：{}", document.getId(), nextVersionNumber);
            String versionFileName = originalFilename + "_v" + nextVersionNumber;
            String difyDocumentId = difyService.uploadDocument(extractedText, versionFileName);

            // 更新文档状态
            document.setDifyDocumentId(difyDocumentId);
            document.setStatus("COMPLETED");
            documentMapper.updateById(document);

            // 创建文档版本记录
            DocumentVersion version = new DocumentVersion();
            version.setDocumentId(document.getId());
            version.setVersionNumber(nextVersionNumber);
            version.setFilePath(null);
            version.setExtractedText(extractedText);
            version.setDifyDocumentId(difyDocumentId);
            version.setIsActive(existingDocument == null); // 新文档的第一个版本默认启用
            version.setCreatedAt(LocalDateTime.now());
            documentVersionMapper.insert(version);
            
            // 如果是新文档的第一个版本，自动启用
            if (existingDocument == null) {
                log.info("新文档的第一个版本自动启用，版本ID：{}", version.getId());
            }

            log.info("文档处理完成，文档ID：{}，版本：{}，Dify文档ID：{}", 
                    document.getId(), nextVersionNumber, difyDocumentId);

            return DocumentUploadResult.builder()
                    .documentId(document.getId())
                    .fileName(originalFilename)
                    .status(document.getStatus())
                    .message(existingDocument != null ? 
                            "文档新版本上传成功，版本号：" + nextVersionNumber : 
                            "文档上传成功")
                    .build();

        } catch (Exception e) {
            log.error("文档处理失败", e);
            throw new DocumentProcessingException("文档处理失败：" + e.getMessage(), e);
        }
    }

    /**
     * 从MultipartFile直接提取文本内容
     * @param file 上传的文件
     * @param fileType 文件类型
     * @return 提取的文本内容
     * @throws IOException 文件读取异常
     */
    private String extractTextFromMultipartFile(MultipartFile file, String fileType) throws IOException {
        log.info("开始从MultipartFile提取文本，文件类型：{}", fileType);
        
        return switch (fileType.toUpperCase()) {
            case "TXT" -> {
                // 直接读取TXT文件内容
                try {
                    String text = new String(file.getBytes(), StandardCharsets.UTF_8);
                    log.info("TXT文本提取完成，文本长度: {}", text.length());
                    yield text;
                } catch (Exception e) {
                    // 如果UTF-8读取失败，尝试使用系统默认编码
                    log.warn("UTF-8编码读取失败，尝试使用系统默认编码: {}", e.getMessage());
                    String text = new String(file.getBytes());
                    log.info("TXT文本提取完成（系统默认编码），文本长度: {}", text.length());
                    yield text;
                }
            }
            case "PDF", "WORD", "EXCEL" -> {
                // 对于其他格式，需要先创建临时文件
                File tempFile = File.createTempFile("temp_", "." + getFileExtension(file.getOriginalFilename()));
                try {
                    file.transferTo(tempFile);
                    String text = DocumentTextExtractor.extractText(tempFile, fileType);
                    log.info("{}文本提取完成，文本长度: {}", fileType, text.length());
                    yield text;
                } finally {
                    // 删除临时文件
                    if (tempFile.exists()) {
                        tempFile.delete();
                        log.debug("临时文件已删除: {}", tempFile.getPath());
                    }
                }
            }
            default -> throw new DocumentProcessingException("不支持的文件类型：" + fileType);
        };
    }

    /**
     * 获取文档列表
     * @param page 页码
     * @param size 每页大小
     * @return 分页结果
     */
    public Page<Document> getDocuments(int page, int size) {
        log.info("查询文档列表，页码：{}，每页大小：{}", page, size);
        Page<Document> pageObj = new Page<>(page, size);
        return documentMapper.selectAllDocuments(pageObj);
    }

    /**
     * 删除文档
     * @param documentId 文档ID
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteDocument(Long documentId) {
        log.info("删除文档，文档ID：{}", documentId);

        Document document = documentMapper.selectById(documentId);
        if (document == null) {
            throw new DocumentProcessingException("文档不存在，ID：" + documentId);
        }

        try {
            // 从Dify删除文档
            if (document.getDifyDocumentId() != null) {
                difyService.deleteDocument(document.getDifyDocumentId());
            }

            // 删除数据库记录
            documentMapper.deleteById(documentId);
            
            // 删除版本记录
            documentVersionMapper.selectByDocumentId(documentId).forEach(version -> {
                documentVersionMapper.deleteById(version.getId());
            });

            log.info("文档删除成功，文档ID：{}", documentId);

        } catch (Exception e) {
            log.error("文档删除失败，文档ID：{}", documentId, e);
            throw new DocumentProcessingException("文档删除失败：" + e.getMessage(), e);
        }
    }

    /**
     * 获取文档版本列表
     * @param documentId 文档ID
     * @return 版本列表
     */
    public List<DocumentVersion> getVersions(Long documentId) {
        log.info("查询文档版本列表，文档ID：{}", documentId);
        return documentVersionMapper.selectByDocumentId(documentId);
    }

    /**
     * 对比两个版本
     * @param version1Id 版本1 ID
     * @param version2Id 版本2 ID
     * @return 版本对比结果
     */
    public VersionComparison compareVersions(Long version1Id, Long version2Id) {
        log.info("对比文档版本，版本1 ID：{}，版本2 ID：{}", version1Id, version2Id);

        DocumentVersion version1 = documentVersionMapper.selectById(version1Id);
        DocumentVersion version2 = documentVersionMapper.selectById(version2Id);

        if (version1 == null || version2 == null) {
            throw new DocumentProcessingException("版本不存在");
        }

        if (!version1.getDocumentId().equals(version2.getDocumentId())) {
            throw new DocumentProcessingException("两个版本不属于同一文档");
        }

        // 基于提取的文本内容进行详细对比
        String text1 = version1.getExtractedText();
        String text2 = version2.getExtractedText();

        List<String> differences = new ArrayList<>();
        
        // 基本信息对比
        differences.add("=== 版本基本信息 ===");
        differences.add("版本 " + version1.getVersionNumber() + " 创建时间: " + version1.getCreatedAt());
        differences.add("版本 " + version2.getVersionNumber() + " 创建时间: " + version2.getCreatedAt());
        differences.add("版本 " + version1.getVersionNumber() + " 文本长度: " + (text1 != null ? text1.length() : 0) + " 字符");
        differences.add("版本 " + version2.getVersionNumber() + " 文本长度: " + (text2 != null ? text2.length() : 0) + " 字符");
        
        // 内容对比
        differences.add("");
        differences.add("=== 内容对比 ===");
        
        if (text1 != null && text2 != null) {
            if (text1.equals(text2)) {
                differences.add("✅ 两个版本内容完全相同");
            } else {
                differences.add("❌ 两个版本内容存在差异");
                
                // 简单的行级对比
                String[] lines1 = text1.split("\n");
                String[] lines2 = text2.split("\n");
                
                differences.add("版本 " + version1.getVersionNumber() + " 行数: " + lines1.length);
                differences.add("版本 " + version2.getVersionNumber() + " 行数: " + lines2.length);
                
                // 计算相似度
                double similarity = calculateSimilarity(text1, text2);
                differences.add("内容相似度: " + String.format("%.2f%%", similarity * 100));
                
                // 找出主要差异
                if (lines1.length != lines2.length) {
                    differences.add("行数差异: " + Math.abs(lines1.length - lines2.length) + " 行");
                }
            }
        } else if (text1 == null && text2 == null) {
            differences.add("⚠️ 两个版本都没有提取到文本内容");
        } else {
            differences.add("⚠️ 其中一个版本没有提取到文本内容");
        }

        return VersionComparison.builder()
                .version1(version1)
                .version2(version2)
                .differences(differences)
                .build();
    }
    
    /**
     * 计算两个文本的相似度
     * @param text1 文本1
     * @param text2 文本2
     * @return 相似度（0-1之间）
     */
    private double calculateSimilarity(String text1, String text2) {
        if (text1 == null || text2 == null) {
            return 0.0;
        }
        
        if (text1.equals(text2)) {
            return 1.0;
        }
        
        // 使用简单的字符级相似度计算
        int maxLength = Math.max(text1.length(), text2.length());
        if (maxLength == 0) {
            return 1.0;
        }
        
        int commonChars = 0;
        int minLength = Math.min(text1.length(), text2.length());
        
        for (int i = 0; i < minLength; i++) {
            if (text1.charAt(i) == text2.charAt(i)) {
                commonChars++;
            }
        }
        
        return (double) commonChars / maxLength;
    }
    
    /**
     * 启用指定版本
     * @param versionId 版本ID
     * @return 启用结果
     */
    @Transactional(rollbackFor = Exception.class)
    public VersionActivationResult activateVersion(Long versionId) {
        log.info("启用版本，版本ID：{}", versionId);
        
        DocumentVersion version = documentVersionMapper.selectById(versionId);
        if (version == null) {
            throw new DocumentProcessingException("版本不存在，ID：" + versionId);
        }
        
        // 检查版本是否已经是启用状态
        if (Boolean.TRUE.equals(version.getIsActive())) {
            return VersionActivationResult.builder()
                    .success(true)
                    .message("该版本已经是启用状态")
                    .versionNumber(version.getVersionNumber())
                    .build();
        }
        
        try {
            // 获取当前启用的版本
            DocumentVersion currentActiveVersion = documentVersionMapper.selectActiveVersionByDocumentId(version.getDocumentId());
            
            // 取消该文档所有版本的启用状态
            documentVersionMapper.deactivateAllVersionsByDocumentId(version.getDocumentId());
            
            // 启用指定版本
            documentVersionMapper.activateVersion(versionId);
            
            // 如果有当前启用版本，需要从Dify知识库中删除
            if (currentActiveVersion != null && currentActiveVersion.getDifyDocumentId() != null) {
                log.info("从Dify删除旧版本，Dify文档ID：{}", currentActiveVersion.getDifyDocumentId());
                try {
                    difyService.deleteDocument(currentActiveVersion.getDifyDocumentId());
                } catch (Exception e) {
                    log.warn("删除Dify旧版本失败，但继续处理：{}", e.getMessage());
                }
            }
            
            // 将新版本上传到Dify知识库
            if (version.getExtractedText() != null) {
                Document document = documentMapper.selectById(version.getDocumentId());
                String versionFileName = document.getFileName() + "_active";
                String newDifyDocumentId = difyService.uploadDocument(version.getExtractedText(), versionFileName);
                
                // 更新版本的Dify文档ID
                version.setDifyDocumentId(newDifyDocumentId);
                documentVersionMapper.updateById(version);
                
                log.info("新版本已上传到Dify，文档ID：{}，版本：{}，Dify文档ID：{}", 
                        version.getDocumentId(), version.getVersionNumber(), newDifyDocumentId);
            }
            
            return VersionActivationResult.builder()
                    .success(true)
                    .message("版本启用成功")
                    .versionNumber(version.getVersionNumber())
                    .previousActiveVersion(currentActiveVersion != null ? currentActiveVersion.getVersionNumber() : null)
                    .build();
                    
        } catch (Exception e) {
            log.error("版本启用失败，版本ID：{}", versionId, e);
            throw new DocumentProcessingException("版本启用失败：" + e.getMessage(), e);
        }
    }
    
    /**
     * 获取文档的当前启用版本
     * @param documentId 文档ID
     * @return 启用版本
     */
    public DocumentVersion getActiveVersion(Long documentId) {
        log.info("获取文档启用版本，文档ID：{}", documentId);
        return documentVersionMapper.selectActiveVersionByDocumentId(documentId);
    }


    /**
     * 验证文件
     * @param file 上传的文件
     */
    private void validateFile(MultipartFile file) {
        if (file == null || file.isEmpty()) {
            throw new DocumentProcessingException("文件不能为空");
        }

        String originalFilename = file.getOriginalFilename();
        if (originalFilename == null || originalFilename.trim().isEmpty()) {
            throw new DocumentProcessingException("文件名不能为空");
        }

        // 验证文件类型
        String fileExtension = getFileExtension(originalFilename).toLowerCase();
        Set<String> allowedTypeSet = new HashSet<>(Arrays.asList(allowedTypes.split(",")));
        
        if (!allowedTypeSet.contains(fileExtension)) {
            throw new DocumentProcessingException("不支持的文件类型：" + fileExtension + "，支持的类型：" + allowedTypes);
        }

        // 验证文件大小（已在配置中限制，这里做额外检查）
        long maxSize = 50 * 1024 * 1024; // 50MB
        if (file.getSize() > maxSize) {
            throw new DocumentProcessingException("文件大小超过限制：" + (maxSize / 1024 / 1024) + "MB");
        }
    }

    /**
     * 确定文件类型
     * @param filename 文件名
     * @return 文件类型：PDF, WORD, EXCEL
     */
    private String determineFileType(String filename) {
        String extension = getFileExtension(filename).toLowerCase();
        
        return switch (extension) {
            case "pdf" -> "PDF";
            case "doc", "docx" -> "WORD";
            case "xls", "xlsx" -> "EXCEL";
            case "txt" -> "TXT";
            default -> throw new DocumentProcessingException("不支持的文件类型：" + extension);
        };
    }

    /**
     * 获取文件扩展名
     * @param filename 文件名
     * @return 扩展名
     */
    private String getFileExtension(String filename) {
        int lastDotIndex = filename.lastIndexOf('.');
        if (lastDotIndex == -1) {
            return "";
        }
        return filename.substring(lastDotIndex + 1);
    }

    /**
     * 生成唯一文件名
     * @param originalFilename 原始文件名
     * @return 唯一文件名
     */
    private String generateUniqueFileName(String originalFilename) {
        String extension = getFileExtension(originalFilename);
        String timestamp = String.valueOf(System.currentTimeMillis());
        String uuid = UUID.randomUUID().toString().substring(0, 8);
        return timestamp + "_" + uuid + "." + extension;
    }

    /**
     * 文档上传结果
     */
    @lombok.Builder
    @lombok.Data
    public static class DocumentUploadResult {
        private Long documentId;
        private String fileName;
        private String status;
        private String message;
    }

    /**
     * 版本对比结果
     */
    @lombok.Builder
    @lombok.Data
    public static class VersionComparison {
        private DocumentVersion version1;
        private DocumentVersion version2;
        private List<String> differences;
    }
    
    /**
     * 版本启用结果
     */
    @lombok.Builder
    @lombok.Data
    public static class VersionActivationResult {
        private Boolean success;
        private String message;
        private Integer versionNumber;
        private Integer previousActiveVersion;
    }
}
